#include "CFightEndMgr.h"
#include "CActCfg.h"
#include "../data/CPlayerOnlineData.h"
#include "../mainctrl.h"
#include "../cmd/dataprepare.h"
#include "../cmdinner/CCmdInnerFightEnd.h"
#include "commclass.h"
#include "MsgFightEnd.pb.h"
#include "../item/CDropItem.h"
#include "MsgMoveTo.pb.h"
#include "MsgGM.pb.h"

unsigned int CFightEndMgr::GetMapID()
{
    int iIndex = 0;
    if (_uiMapID <= 0)
    {
        iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActCfg(ACT_ID_FIGHT_END);
        if (iIndex < 0)
        {
            CT_ERROR(("fight end act(%d) config empty!", ACT_ID_FIGHT_END));
            return 0;
        }
        CActCfgData& stActCfgData =
            CMainCtrl::m_pstMain->m_stActMgr.GetActCfg(iIndex);

        iIndex = CMainCtrl::m_pstMain->m_stSceneMgr.FindSceneCfg(
            stActCfgData.GetSceneID());
        if (iIndex < 0)
        {
            CT_ERROR(("fight end scene(%d) config in act(%d) empty!",
                stActCfgData.GetSceneID(),ACT_ID_FIGHT_END));
            return 0;
        }
        CSceneCfgData& stSceneCfgData =
            CMainCtrl::m_pstMain->m_stSceneMgr.GetSceneCfg(iIndex);

        _uiMapID = stSceneCfgData.GetMapID();
    }

    return _uiMapID;
}

unsigned int CFightEndMgr::GetRelayMapID()
{
    int iIndex = 0;
    if (_uiRelayMapID <= 0)
    {
        iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActCfg(ACT_ID_FIGHT_END);
        if (iIndex < 0)
        {
            CT_ERROR(("fight end act(%d) config empty!", ACT_ID_FIGHT_END));
            return 0;
        }
        CActCfgData& stActCfgData =
            CMainCtrl::m_pstMain->m_stActMgr.GetActCfg(iIndex);

        iIndex = CMainCtrl::m_pstMain->m_stSceneMgr.FindSceneCfg(
            stActCfgData.GetSceneID());
        if (iIndex < 0)
        {
            CT_ERROR(("fight end scene(%d) config in act(%d) empty!",
                stActCfgData.GetSceneID(),ACT_ID_FIGHT_END));
            return 0;
        }
        CSceneCfgData& stSceneCfgData =
            CMainCtrl::m_pstMain->m_stSceneMgr.GetSceneCfg(iIndex);

        _uiRelayMapID = stSceneCfgData.GetRelayMapID();
    }

    return _uiRelayMapID;
}

int CFightEndMgr::GetMapPos(int iIndex, unsigned short& usPosX,
        unsigned short& usPosY)
{
    if (iIndex > 0 && iIndex <= MAX_FIGHT_END_ROLE_TOTAL)
    {
        usPosY = iIndex % MAX_FIGHT_END_ROLE_SIDE;
        if (0 == usPosY)
        {
            usPosY = MAX_FIGHT_END_ROLE_SIDE;
        }

        double dValue = iIndex * 1.0;
        dValue /= (MAX_FIGHT_END_ROLE_SIDE * 1.0);
        usPosX = (unsigned short)(ceil(dValue));//向上取整
    }
    else
    {
        usPosX = 0;
        usPosY = 0;
        CT_ERROR(("fight end get max pos but unknow index(%d)",iIndex));
    }

    return 0;
}

int CFightEndMgr::SetMapPos(unsigned int uiMapID, int& iPosIndex,
        unsigned short& usPosX, unsigned short& usPosY,
        CPlayerBaseInfo& stPlayerBaseInfo)
{
    iPosIndex = -1; //初始值必须是非法值
    for (int i = 0; i < _auiRoleList.Size(); ++i)
    {
        if (_auiRoleList[i] == stPlayerBaseInfo._uiGID)
        {
            CT_ERROR(("fight end role(%u) already in map pos array!",
                stPlayerBaseInfo._uiGID));

            iPosIndex = i;
            break;
        }

        if (iPosIndex < 0 && _auiRoleList[i] == 0)
        {
            iPosIndex = i;
        }
    }
    
    if (iPosIndex >= 0)
    {
        _auiRoleList[iPosIndex] = stPlayerBaseInfo._uiGID;
    }

    return GetMapPos(iPosIndex + 1, usPosX, usPosY);
}

//活动开启
//必须通过引用的方式将活动实体传过来而不能再在内部find活动
int CFightEndMgr::ActOpen(CActCfgData& stActCfgData)
{
    ClearRoleData();

    CSingleMapView::MAP_VIEW_NOTIFY_USERS_ARRAY auiMapUserList;
    CMainCtrl::m_pstMain->m_stMapViews.GetAllMapUsers(GetMapID(),
        auiMapUserList);
    for (int i = 0; i < auiMapUserList.Size(); ++i)
    {
        MoveOutRoleNoAns(auiMapUserList[i]);
    }

    return 0;
}

//活动关闭
int CFightEndMgr::ActClose(CActCfgData& stActCfgData)
{
    //应该下发信息 踢出正在等待的玩家
    int iRet = 0;
    CSingleMapView::MAP_VIEW_NOTIFY_USERS_ARRAY auiMapUserList;
    CMainCtrl::m_pstMain->m_stMapViews.GetAllMapUsers(GetMapID(),
        auiMapUserList);
    for (int i = 0; i < auiMapUserList.Size(); ++i)
    {
        //MoveOutRole只踢出玩家 没有下发活动相关的信息
        iRet = MoveOutRole(auiMapUserList[i]);
        if (iRet)
        {
            CT_ERROR(("fight end role(%u) move out error(%d)",
                auiMapUserList[i],iRet));
        }
    }

    return 0;
}

int CFightEndMgr::EnterScene(unsigned int uiMapID, unsigned short& usPosX,
        unsigned short& usPosY, CPlayerBaseInfo& stPlayerBaseInfo,
        CPlayerOnlineData& stPlayerOnlineData)
{
    int iRet = 0;

    if (GetMapID() != uiMapID)
    {
        return 0;
    }

    if (IsNeedClearMap())
    {
        ClearRoleData();

        CSingleMapView::MAP_VIEW_NOTIFY_USERS_ARRAY auiMapUserList;
        CMainCtrl::m_pstMain->m_stMapViews.GetAllMapUsers(GetMapID(),
            auiMapUserList);
        for (int i = 0; i < auiMapUserList.Size(); ++i)
        {
            MoveOutRoleNoAns(auiMapUserList[i]);
        }
    }

    if (!CMainCtrl::m_pstMain->m_stActMgr.IsActOpen(ACT_ID_FIGHT_END))
    {
        //非活动期间不允许进入
        return ERROR_FIGHT_END_ACT_NO_OPEN;
    }

    //检查系统是否开启
    if (!CMainCtrl::m_pstMain->m_stCommConfigLoader.IsOpen(SYS_OPEN_COND_ID_57,
            stPlayerBaseInfo, stPlayerOnlineData))
    {
        return ERROR_SYS_NOT_OPEN;
    }

    if (stPlayerOnlineData._stUserStorage.GetBagEmptyGridCount() <
            MACRO_FIGHT_END_ENTER_BAG_NUM)
    {
        //没有足够的背包格子不能参加
        return ERROR_FIGHT_END_BAG_NOT_ENOUGH;
    }

    if (CMainCtrl::m_pstMain->m_stMapViews.IsRoleInMap(GetMapID(),
            stPlayerBaseInfo._uiGID))
    {
        //已经在活动地图场景 不出错返回 坐标被重写 留待随机 地图限制存在遗漏
        CT_ERROR(("fight end act(%d) role(%u) already in map(%u)",
            ACT_ID_FIGHT_END,stPlayerBaseInfo._uiGID,GetMapID()));
        return 0;
    }

    int iMapUserNum =
            CMainCtrl::m_pstMain->m_stMapViews.GetAllMapUsersNum(GetMapID());
    if (iMapUserNum >= MAX_FIGHT_END_ROLE_TOTAL)
    {
        //上一场人数已满 未能触发 这里先结算一次 战斗触发存在遗漏
        CT_ERROR(("fight end act(%d) role(%u) join but map(%u) user full(%d)",
            ACT_ID_FIGHT_END,stPlayerBaseInfo._uiGID,GetMapID(),iMapUserNum));
    }

    int iPosIndex = 0;
    iRet = SetMapPos(uiMapID, iPosIndex, usPosX, usPosY, stPlayerBaseInfo);
    CT_RETURN(iRet);

    CCmdInnerFightEnd* pstCmd =
        (CCmdInnerFightEnd*)CT_CMDFACTORY->CreateCmd(
            ID_MAIN_INNER_FIGHT_END);
    if (!pstCmd)
    {
        CT_ERROR(("create CCmdInnerFightEnd error"));
        return RET_SYS_NULL_POINTER;
    }
    
    pstCmd->pstMainCtrl = CMainCtrl::m_pstMain;
    pstCmd->_uiGID = stPlayerBaseInfo._uiGID;
    pstCmd->_iSubCmd = CMD_INNER_FIGHT_END_SEND_INFO;
    pstCmd->_bIsLeft = false;
    if (iPosIndex < MAX_FIGHT_END_ROLE_SIDE)
    {
        pstCmd->_bIsLeft = true;
    }

    return pstCmd->Do(NULL);
}

void CFightEndMgr::RoleMoveOut(unsigned int uiGID)
{
    if (!CMainCtrl::m_pstMain->m_stActMgr.IsActOpen(ACT_ID_FIGHT_END))
    {
        //非活动期间不需要清除
        return;
    }

    for (int i = 0; i < _auiRoleList.Size(); ++i)
    {
        if (_auiRoleList[i] == uiGID)
        {
            _auiRoleList[i] = 0;
        }
    }
}

void CFightEndMgr::UpdateFightEndData(CPlayerDetailInfoEx1& stPlayerDetailEx1)
{
    CVarObjectKey stKey;
    stKey.m_chDataType = DT_PLAYER_DETAIL_EX1_INFO;
    stKey.m_u64ID = stPlayerDetailEx1._uiGID;
    CMainCtrl::m_pstMain->UpdateData(stKey, stPlayerDetailEx1, VOP_UPDATE);
}

int CFightEndMgr::CheckFightEndData(CPlayerDetailInfoEx1& stPlayerDetailEx1)
{
    int iIndex = 0;
    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActCfg(ACT_ID_FIGHT_END);
    if (iIndex < 0)
    {
        CT_ERROR(("fight end act(%d) config empty!", ACT_ID_FIGHT_END));
        return 0;
    }
    CActCfgData& stActCfgData =
        CMainCtrl::m_pstMain->m_stActMgr.GetActCfg(iIndex);

    if (stPlayerDetailEx1._stFightEnd._iLastEndTime !=
            stActCfgData.GetEndTime())
    {
        stPlayerDetailEx1._stFightEnd._chAwardNum = 0;
        stPlayerDetailEx1._stFightEnd._iLastEndTime =
            stActCfgData.GetEndTime();

        UpdateFightEndData(stPlayerDetailEx1);
    }

    return 0;
}

int CFightEndMgr::MoveOutRole(unsigned int uiGID)
{
    CCmdInnerFightEnd* pstCmd =
        (CCmdInnerFightEnd*)CT_CMDFACTORY->CreateCmd(
            ID_MAIN_INNER_FIGHT_END);
    if (!pstCmd)
    {
        CT_ERROR(("create CCmdInnerFightEnd error"));
        return RET_SYS_NULL_POINTER;
    }
    
    pstCmd->pstMainCtrl = CMainCtrl::m_pstMain;
    pstCmd->_uiGID = uiGID;
    pstCmd->_iSubCmd = CMD_INNER_FIGHT_END_LEAVE_MAP;
    return pstCmd->Do(NULL);
}

int CFightEndMgr::MoveOutRoleNoAns(unsigned int uiGID)
{
    CCmdInnerFightEnd* pstCmd =
        (CCmdInnerFightEnd*)CT_CMDFACTORY->CreateCmd(
            ID_MAIN_INNER_FIGHT_END);
    if (!pstCmd)
    {
        CT_ERROR(("create CCmdInnerFightEnd error"));
        return RET_SYS_NULL_POINTER;
    }
    
    pstCmd->pstMainCtrl = CMainCtrl::m_pstMain;
    pstCmd->_uiGID = uiGID;
    pstCmd->_iSubCmd = CMD_INNER_FIGHT_END_LEAVE_MAP_NO_ANS;
    return pstCmd->Do(NULL);
}

void CFightEndMgr::CheckBagGrid()
{
    CSingleMapView::MAP_VIEW_NOTIFY_USERS_ARRAY auiMapUserList;
    CMainCtrl::m_pstMain->m_stMapViews.GetAllMapUsers(GetMapID(),
        auiMapUserList);

    int iRet = 0;

    for (int i = 0; i < auiMapUserList.Size() && i < MAX_FIGHT_END_ROLE_TOTAL;
            ++i)
    {
        CCmdInnerFightEnd* pstCmd =
            (CCmdInnerFightEnd*)CT_CMDFACTORY->CreateCmd(
                ID_MAIN_INNER_FIGHT_END);
        if (!pstCmd)
        {
            CT_ERROR(("create CCmdInnerFightEnd error"));
            continue;
        }
        
        pstCmd->pstMainCtrl = CMainCtrl::m_pstMain;
        pstCmd->_uiGID = auiMapUserList[i];
        pstCmd->_iSubCmd = CMD_INNER_FIGHT_END_CHECK_BAG;

        iRet = pstCmd->Do(NULL);
        if (iRet)
        {
            CT_ERROR(("fight end check role(%u) bag error(%d)!",
                auiMapUserList[i], iRet));
        }
    }
}

void CFightEndMgr::TriggerBattle()
{
    int iMapUserNum =
            CMainCtrl::m_pstMain->m_stMapViews.GetAllMapUsersNum(GetMapID());
    if (iMapUserNum < MAX_FIGHT_END_ROLE_TOTAL)
    {
        //人数不足不开启战斗
        return;
    }

    CSingleMapView::MAP_VIEW_NOTIFY_USERS_ARRAY auiMapUserList;
    CMainCtrl::m_pstMain->m_stMapViews.GetAllMapUsers(GetMapID(),
        auiMapUserList);
    if (auiMapUserList.Size() < MAX_FIGHT_END_ROLE_TOTAL)
    {
        //人数不足不开启战斗
        return;
    }

    CTLib::CTArray<bool, MAX_FIGHT_END_ROLE_TOTAL> aHasSwap;
    aHasSwap.m_iUsedCount = aHasSwap.GetCount();
    for (int i = 0; i < aHasSwap.Size(); ++i)
    {
        aHasSwap[i] = false;
    }

    int iSwapIndex = -1;
    unsigned int uiGIDTmp = 0;
    for (int i = 0; i < auiMapUserList.Size() && i < MAX_FIGHT_END_ROLE_TOTAL; )//不要递增 放在逻辑内部
    {
        iSwapIndex = -1;
        if (i < aHasSwap.Size() && aHasSwap[i])//当前元素已交换过
        {
            ++i;
            continue;
        }

        for (int j = 0; j < _auiRoleList.Size(); ++j)
        {
            if (auiMapUserList[i] == _auiRoleList[j])
            {
                iSwapIndex = j;
                break;
            }
        }

        if (iSwapIndex >= 0 && iSwapIndex < auiMapUserList.Size())
        {
            if (iSwapIndex != i)
            {
                uiGIDTmp = auiMapUserList[i];
                auiMapUserList[i] = auiMapUserList[iSwapIndex];
                auiMapUserList[iSwapIndex] = uiGIDTmp;
            }

            if (iSwapIndex < aHasSwap.Size())
            {
                aHasSwap[iSwapIndex] = true;
            }
        }
        else
        {
            ++i;
        }
    }

    //准备数据并开启战斗
    CCmdInnerFightEnd* pstCmd =
        (CCmdInnerFightEnd*)CT_CMDFACTORY->CreateCmd(
            ID_MAIN_INNER_FIGHT_END);
    if (!pstCmd)
    {
        CT_ERROR(("create CCmdInnerFightEnd error"));
        return;
    }
    
    pstCmd->pstMainCtrl = CMainCtrl::m_pstMain;
    pstCmd->_uiGID = 0;
    pstCmd->_iSubCmd = CMD_INNER_FIGHT_END_PREPARE_DATA;

    pstCmd->_stFightEndData.Clear();

    for (int i = 0; i < auiMapUserList.Size()
            && i < pstCmd->_stFightEndData.GetRoleSize(); ++i)
    {
        CFightEndUnit& stRoleUnit = pstCmd->_stFightEndData.GetRoleUnit(i);
        stRoleUnit.SetGID(auiMapUserList[i]);

        CT_TRACE(("TriggerBattle Map User List: %d %u",i,auiMapUserList[i]));
    }

    SetNeedClearMap(true);

    pstCmd->Do(NULL);
}

int CFightEndMgr::DealBattle(CFightEndData& stRolesData, bool& bIsLeftWin,
        int& iWinIndex, bool& bIsReverWin)
{
    int iRet = 0;
    int iIndex = 0;
    int iLeftIndex = -1;
    int iRightIndex = -1;
    int iBattleIndex = 0;

    iWinIndex = -1;
    bIsReverWin = false;
    int iWinIndexTmp = -1;
    int iWinTimeSum = 0;
    bool bLeftWinThisTime = false;

    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActCfg(ACT_ID_FIGHT_END);
    CT_CHECK(iIndex, ERROR_ACT_EMPTY_CFG);

    CActCfgData& stActCfgData =
        CMainCtrl::m_pstMain->m_stActMgr.GetActCfg(iIndex);

    while (true)
    {
        iLeftIndex = -1;
        iRightIndex = -1;
        bLeftWinThisTime = false;

        ++iBattleIndex;

        for (int i = 0; i < stRolesData.GetRoleSize() &&
                i < MAX_FIGHT_END_ROLE_SIDE; ++i)
        {
            CFightEndUnit& stRoleUnit = stRolesData.GetRoleUnit(i);
            if (stRoleUnit.GetGID() > 0 && stRoleUnit.IsLife())
            {
                iLeftIndex = i;
                break;
            }
        }

        for (int i = MAX_FIGHT_END_ROLE_SIDE; i < stRolesData.GetRoleSize() &&
                i < MAX_FIGHT_END_ROLE_TOTAL; ++i)
        {
            CFightEndUnit& stRoleUnit = stRolesData.GetRoleUnit(i);
            if (stRoleUnit.GetGID() > 0 && stRoleUnit.IsLife())
            {
                iRightIndex = i - MAX_FIGHT_END_ROLE_SIDE;
                break;
            }
        }

        //左方胜出
        if (iRightIndex < 0 || iRightIndex >= stRolesData.GetRightTeamSize())
        {
            bIsLeftWin = true;

            if (iWinTimeSum >= MAX_FIGHT_END_ROLE_SIDE)//恰好三场所以才能复用此宏
            {
                iWinIndex = iWinIndexTmp;
                if (iWinIndexTmp == MAX_FIGHT_END_ROLE_SIDE - 1 ||
                    iWinIndexTmp == 2 * MAX_FIGHT_END_ROLE_SIDE - 1)
                {
                    bIsReverWin = true;
                }
            }

            return 0;
        }

        //右方胜出
        if (iLeftIndex < 0 || iLeftIndex >= stRolesData.GetLeftTeamSize())
        {
            bIsLeftWin = false;

            if (iWinTimeSum >= MAX_FIGHT_END_ROLE_SIDE)//恰好三场所以才能复用此宏
            {
                iWinIndex = iWinIndexTmp;
                if (iWinIndexTmp == MAX_FIGHT_END_ROLE_SIDE - 1 ||
                    iWinIndexTmp == 2 * MAX_FIGHT_END_ROLE_SIDE - 1)
                {
                    bIsReverWin = true;
                }
            }

            return 0;
        }

        iRet = DealBattle(stRolesData, iLeftIndex, iRightIndex, iBattleIndex,
            stActCfgData.GetType(), bLeftWinThisTime);
        if (iRet)
        {
            CT_ERROR((""));
            return iRet;
        }

        if (bLeftWinThisTime)
        {
            //单场左方胜出
            if (iWinIndexTmp == iLeftIndex)
            {
                ++iWinTimeSum;
            }
            else
            {
                iWinIndexTmp = iLeftIndex;
                iWinTimeSum = 1;
            }
        }
        else
        {
            //单场右方胜出
            if (iWinIndexTmp == iRightIndex + MAX_FIGHT_END_ROLE_SIDE)
            {
                ++iWinTimeSum;
            }
            else
            {
                iWinIndexTmp = iRightIndex + MAX_FIGHT_END_ROLE_SIDE;
                iWinTimeSum = 1;
            }
        }
    }
}

int CFightEndMgr::DealBattle(CFightEndData& stRolesData, int iLeftIndex,
        int iRightIndex, int iBattleIndex, int iActType, bool& bLeftWinThisTime)
{
    int iRet = 0;
    int iIndex = 0;
    int iWinIndex = -1;
    int iLoseIndex = -1;

    MsgAnsFightEnd stAns;
    stAns.set_sub_type(CMD_FIGHT_END_SUB_BATTLE);
    stAns.set_end_time(
        CMainCtrl::m_pstMain->m_stActMgr.GetEndTime(ACT_ID_FIGHT_END));

    MsgFightEndBattleUnit* pstBattleUnit = stAns.mutable_battle_unit();
    if (!pstBattleUnit)
    {
        CT_ERROR(("MsgFightEndBattleUnit pointer null!"));
        return RET_SYS_NULL_POINTER;
    }

    MsgBattleResult* pstBattleResult = pstBattleUnit->mutable_battle_result();
    if (!pstBattleResult)
    {
        CT_ERROR(("MsgBattleResult pointer null!"));
        return RET_SYS_NULL_POINTER;
    }

    MsgBattleExtInfo* pstBattleExtInfo =
        pstBattleResult->mutable_battle_ext_info();
    if (!pstBattleExtInfo)
    {
        CT_ERROR(("MsgBattleExtInfo pointer null!"));
        return RET_SYS_NULL_POINTER;
    }

    pstBattleUnit->set_battle_index(iBattleIndex);

    for (int i = 0; i < stRolesData.GetRoleSize(); ++i)
    {
        MsgFightEndRoleIcon* pstRoleIcon = pstBattleUnit->add_icon_list();
        if (!pstRoleIcon)
        {
            CT_ERROR(("MsgFightEndRoleIcon pointer null!"));
            continue;
        }

        CFightEndUnit& stRoleUnit = stRolesData.GetRoleUnit(i);

        iIndex = CMainCtrl::m_pstMain->m_stPlayerBaseInfoHash.HashFind(
            stRoleUnit.GetGID());
        if (iIndex < 0)
        {
            CT_ERROR(("no base data user(%u)", stRoleUnit.GetGID()));
            continue;
        }
        CPlayerBaseInfo& stPlayerBase =
            CMainCtrl::m_pstMain->m_stPlayerBaseInfoHash[iIndex];

        pstRoleIcon->set_pos(i+1);
        pstRoleIcon->set_is_life(stRoleUnit.IsLife());
        pstRoleIcon->set_win_num(stRoleUnit.GetWinNum());
        pstRoleIcon->set_is_male(stPlayerBase._ucIsMale);
        pstRoleIcon->set_career(stPlayerBase._ucCareer);
        pstRoleIcon->set_role_name(stPlayerBase._sRoleName());
    }

    iRet = CMainCtrl::m_pstMain->m_stBattleMgr.DealPvPBattle(
        stRolesData.GetLeftTeam(iLeftIndex),
        stRolesData.GetRightTeam(iRightIndex), (*pstBattleResult),
        iActType);
    if (iRet)
    {
        CT_ERROR(("DealPvPBattle index(%d) error(%d)", iBattleIndex,iRet));
        return iRet;
    }

    pstBattleExtInfo->set_map_id(GetRelayMapID());
    pstBattleExtInfo->set_pos_x(0);
    pstBattleExtInfo->set_pos_y(0);

    if (pstBattleResult->result() == BATTLE_RESULT_WIN)//左方胜
    {
        bLeftWinThisTime = true;
        iWinIndex = iLeftIndex;
        iLoseIndex = iRightIndex + MAX_FIGHT_END_ROLE_SIDE;
    }
    else
    {
        bLeftWinThisTime = false;
        iWinIndex = iRightIndex + MAX_FIGHT_END_ROLE_SIDE;
        iLoseIndex = iLeftIndex;
    }

    pstBattleUnit->set_win_icon_pos(iWinIndex + 1);
    pstBattleUnit->set_lose_icon_pos(iLoseIndex + 1);

    CFightEndUnit& stWinRoleUnit = stRolesData.GetRoleUnit(iWinIndex);
    CFightEndUnit& stLoseRoleUnit = stRolesData.GetRoleUnit(iLoseIndex);

    stWinRoleUnit.AddWinNum();
    stLoseRoleUnit.SetLife(false);

    //胜利者宣言 建议放到战斗内部结构 用战斗喊话
    iIndex = CMainCtrl::m_pstMain->m_stPlayerDetailInfoHash.HashFind(
        stWinRoleUnit.GetGID());
    if (iIndex >= 0)
    {
        CPlayerDetailInfo& stPlayerDetail =
            CMainCtrl::m_pstMain->m_stPlayerDetailInfoHash[iIndex];
        pstBattleResult->set_battle_speak(
            stPlayerDetail._stUserArenaData._szWinSay());
    }
    else
    {
        CT_ERROR(("no detail data user(%u)", stWinRoleUnit.GetGID()));
    }

    //下发全员战斗信息 注意立即发出
    for (int i = 0; i < stRolesData.GetRoleSize(); ++i)
    {
        CFightEndUnit& stRoleUnit = stRolesData.GetRoleUnit(i);
        if (stRoleUnit.GetGID() <= 0)
        {
            continue;
        }

        stAns.set_gid(stRoleUnit.GetGID());
        if (i < MAX_FIGHT_END_ROLE_SIDE)
        {
            stAns.set_is_left(1);
        }
        else
        {
            stAns.set_is_left(0);
        }

        CMainCtrl::m_pstMain->NotifyOnlineUser(stRoleUnit.GetGID(),
            ID_MAIN_FIGHT_END, stAns, false);
    }

    CMainCtrl::m_pstMain->FlushSendCache();

    return 0;
}

int CFightEndMgr::BattleReport(CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfoEx1& stPlayerDetailEx1,
        CPlayerOnlineData& stPlayerOnlineData, bool bIsLeft, bool bIsBattleWin)
{
    int iRet = 0;
    int iIndex = 0;
    iRet = CheckFightEndData(stPlayerDetailEx1);
    CT_RETURN(iRet);

    MsgAnsFightEnd stAns;
    stAns.set_sub_type(CMD_FIGHT_END_SUB_RESULT);
    stAns.set_gid(stPlayerBase._uiGID);
    stAns.set_end_time(
        CMainCtrl::m_pstMain->m_stActMgr.GetEndTime(ACT_ID_FIGHT_END));
    if (bIsLeft)
    {
        stAns.set_is_left(1);
    }
    else
    {
        stAns.set_is_left(0);
    }

    MsgFightEndBattleOver* pstMsgBattleOver = stAns.mutable_battle_over();
    if (!pstMsgBattleOver)
    {
        CT_ERROR(("MsgFightEndBattleOver pointer null!"));
        return RET_SYS_NULL_POINTER;
    }

    if (bIsBattleWin)
    {
        pstMsgBattleOver->set_is_win(1);
    }
    else
    {
        pstMsgBattleOver->set_is_win(0);
    }

    pstMsgBattleOver->set_award_max(MACRO_FIGHT_END_MAX_AWARD_TIME);

    do{
        if (!bIsBattleWin || stPlayerDetailEx1._stFightEnd._chAwardNum
                >= MACRO_FIGHT_END_MAX_AWARD_TIME)
        {
            break;
        }

        if (stPlayerOnlineData._stUserStorage.GetBagEmptyGridCount() <
                MACRO_FIGHT_END_BATTLE_BAG_NUM)
        {
            break;
        }

        //触发任务加活跃度
        CMainCtrl::m_pstMain->m_stDailyTaskMgr.TriggerTaskFinish(
            stPlayerOnlineData._stUserDailyTask, DAILY_TASK_ID_31);

        iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindFightEndCfg(
            stPlayerBase._shLevel);
        if (iIndex < 0)
        {
            CT_ERROR(("fight end config empty (level = %d)!",
                stPlayerBase._shLevel));
            break;
        }

        CFightEndCfgData& stFightEndCfgData =
            CMainCtrl::m_pstMain->m_stActMgr.GetFightEndCfg(iIndex);
        if (stFightEndCfgData.GetDropItemSize() <= 0)
        {
            CT_ERROR(("fight end config drop item empty (level = %d)!",
                stFightEndCfgData.GetLevel()));
            break;
        }

        CDropItem stDropItem;
        for (int i = 0; i < stFightEndCfgData.GetDropItemSize(); ++i)
        {
            CDropItemData& stDropItemData = stFightEndCfgData.GetDropItem(i);

            stDropItem.DropItem(stDropItemData._usItemConfigID,
                stDropItemData._ucItemType, stDropItemData._iItemCount);
        }
        
        //这里不再检查背包 如果奖励增加 增大战斗前背包格子数检查即可

        stDropItem.SetOssModule(OSS_MODULE_FIGHT_END);
        iRet = CMainCtrl::m_pstMain->m_stItemMgr.DropItem(NULL,
            stPlayerBase._uiGID, stDropItem);
        if (iRet)
        {
            CT_ERROR(("fight end (level = %d) drop role(%u) item error(%d)!",
                stFightEndCfgData.GetLevel(),stPlayerBase._uiGID, iRet));
        }
    
        //不定时炸弹
        stDropItem.GetPBMsg(stPlayerBase._uiGID,
            *(pstMsgBattleOver->mutable_award_item()));
    
        stPlayerDetailEx1._stFightEnd._chAwardNum += 1;

        pstMsgBattleOver->set_award_time(
            stPlayerDetailEx1._stFightEnd._chAwardNum);

        UpdateFightEndData(stPlayerDetailEx1);

    }while(0);

    return CMainCtrl::m_pstMain->NotifyOnlineUser(stPlayerBase._uiGID,
        ID_MAIN_FIGHT_END, stAns, true);
}

int CFightEndMgr::MoveOutRoleFromMap(unsigned int uiMapID,
        CPlayerBaseInfo& stPlayerBase, CPlayerOnlineData& stPlayerOnlineData)
{
    if (uiMapID == stPlayerBase._uiMapID)
    {
        CT_ERROR(("role(%u) already in map(%u) no need move!",
            stPlayerBase._uiGID, uiMapID));
        return 0;
    }

    int iRet = 0;
    MsgAnsMoveTo stAns;
    stAns.set_gid(stPlayerBase._uiGID);
    stAns.set_map_id(stPlayerBase._uiMapID);
    stAns.set_pos_x(stPlayerBase._usXPos);
    stAns.set_pos_y(stPlayerBase._usYPos);

    PBMsgHead stMsgHead;

    stMsgHead.set_version(0);
    stMsgHead.set_time(CMainCtrl::m_pstMain->m_iNow);
    stMsgHead.set_msgact(0);
    stMsgHead.set_msgid(ID_MAIN_MAP_MOVE);
    stMsgHead.set_msgret(0);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    CMainCtrl::m_pstMain->m_stEncodeBuf.Clear();

    CMainCtrl::m_pstMain->EncodePBMsg(stMsgHead,
        CMainCtrl::m_pstMain->m_stEncodeBuf);

    CMainCtrl::m_pstMain->EncodePBMsg(stAns,
        CMainCtrl::m_pstMain->m_stEncodeBuf);

    iRet = CMainCtrl::m_pstMain->NotifyOnlineUser(stPlayerBase._uiGID,
        CMainCtrl::m_pstMain->m_stEncodeBuf);

    if (iRet)
    {
        CT_ERROR(("notify role(%u) message error(%d)!", stPlayerBase._uiGID,
            iRet));
    }

    return 0;
}

int CFightEndMgr::MoveOutRoleWithoutMoveAns(unsigned int uiMapID,
        CPlayerBaseInfo& stPlayerBase, CPlayerOnlineData& stPlayerOnlineData)
{
    if (uiMapID == stPlayerBase._uiMapID)
    {
        CT_ERROR(("role(%u) already in map(%u) no need move!",
            stPlayerBase._uiGID, uiMapID));
        return 0;
    }

    stPlayerOnlineData._uiNowMapID = stPlayerBase._uiMapID;
    stPlayerOnlineData._usMapPosX = stPlayerBase._usXPos;
    stPlayerOnlineData._usMapPosY = stPlayerBase._usYPos;

    int iRet = 0;

    //离开通知
    CSingleMapView::MAP_VIEW_NOTIFY_USERS_ARRAY astNotifyUsers;
    iRet = CMainCtrl::m_pstMain->m_stMapViews.LeaveMap(uiMapID,
        stPlayerBase._uiGID, astNotifyUsers);
    if (iRet != 0)
    {
        CT_ERROR(("role(%u) leave map(%u) error(%d)", stPlayerBase._uiGID,
            uiMapID,iRet));
    }

    if (uiMapID < MIN_MAP_ID_NEED_NOT_SYNC)
    {
        for (int i = 0; i < astNotifyUsers.Size(); ++i)
        {
            if (astNotifyUsers[i] != stPlayerBase._uiGID)
            {
                CMainCtrl::m_pstMain->NotifyOnlineUser(astNotifyUsers[i],
                    CMainCtrl::m_pstMain->m_stEncodeBuf);
            }
        }
    }
    
    //进入通知
    iRet = CMainCtrl::m_pstMain->m_stMapViews.IntoMap(stPlayerBase._uiMapID,
        stPlayerBase._uiGID, false, stPlayerBase._usXPos, stPlayerBase._usYPos);
    if (iRet != 0)
    {
        CT_ERROR(("role(%u) into map(%u) error(%d)", stPlayerBase._uiGID,
            stPlayerBase._uiMapID, iRet));
    } 

    CMainCtrl::m_pstMain->FlushSendCache();

    return 0;
}

int CFightEndMgr::GMDealFightEnd(CPlayerDetailInfoEx1& stPlayerDetailEx1,
        MsgAnsGMPlayer& stAns)
{
    CTSizeString<MAX_BATTLE_NAME_BUFF> szNameStr;

    szNameStr.Cat("一战到底状态:%d",
        CMainCtrl::m_pstMain->m_stActMgr.IsActOpen(ACT_ID_FIGHT_END));

    CSingleMapView::MAP_VIEW_NOTIFY_USERS_ARRAY auiMapUserList;
    CMainCtrl::m_pstMain->m_stMapViews.GetAllMapUsers(GetMapID(),
        auiMapUserList);

    szNameStr.Cat(" 场景人数:%d",auiMapUserList.Size());
    for (int i = 0; i < auiMapUserList.Size(); ++i)
    {
        szNameStr.Cat(" %u",auiMapUserList[i]);
    }

    szNameStr.Cat(" 位置标记:");
    for (int i = 0; i < _auiRoleList.Size(); ++i)
    {
        szNameStr.Cat(" %u",_auiRoleList[i]);
    }

    szNameStr.Cat("\nGID:%u 奖励次数:%d 活动开始时间:%d",
        stPlayerDetailEx1._uiGID, stPlayerDetailEx1._stFightEnd._chAwardNum,
        stPlayerDetailEx1._stFightEnd._iLastEndTime);

    stAns.set_name(szNameStr.Get());

    return 0;
}

